import { Router } from 'express';
import multer from 'multer';
import path from 'path';
import fs from 'fs';
import Paths from '@src/common/constants/Paths';
import { prisma } from '@src/common/database';
import { jsonResponse } from '@src/common/util/bigint-serializer';
import { chatSubscribers, sendToChatRoom } from './common/chat-sse';
import { compressChatImage } from '@src/utils/imageCompression';

const router = Router();

// 配置聊天室图片上传
const chatImageStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    const uploadPath = path.join(__dirname, '../../uploads/chat-images');
    // 确保目录存在
    if (!fs.existsSync(uploadPath)) {
      fs.mkdirSync(uploadPath, { recursive: true });
    }
    cb(null, uploadPath);
  },
  filename: (req, file, cb) => {
    const timestamp = Date.now();
    const ext = path.extname(file.originalname);
    const name = `chat-${timestamp}-${Math.random().toString(36).substring(2)}${ext}`;
    cb(null, name);
  }
});

const chatImageUpload = multer({
  storage: chatImageStorage,
  limits: {
    fileSize: 20 * 1024 * 1024, // 20MB - 允许稍大的原始文件，压缩后会变小
  },
  fileFilter: (req, file, cb) => {
    // 只允许图片文件
    if (file.mimetype.startsWith('image/')) {
      cb(null, true);
    } else {
      cb(new Error('이미지 파일만 업로드 가능합니다'));
    }
  }
});

// 工具：获取当前登录用户（基于 auth/me 的逻辑简化复用）
async function getCurrentUser(req: any) {
  try {
    const sid = req.cookies?.['sid'];
    if (!sid) return null;
    const sess = await prisma.userSession.findUnique({ where: { id: BigInt(sid) } });
    if (!sess || new Date(sess.expiredAt) < new Date()) return null;
    const user = await prisma.user.findUnique({ where: { id: sess.userId } });
    return user;
  } catch {
    return null;
  }
}

// ===== 聊天室图片上传：POST /api/chat/rooms/:id/upload-image
router.post(Paths.Chat.Rooms + '/:id/upload-image', chatImageUpload.single('image'), async (req, res) => {
  try {
    const user = await getCurrentUser(req);
    if (!user) return res.status(401).json({ error: '로그인되지 않음' });

    const file = req.file as Express.Multer.File | undefined;
    if (!file) return res.status(400).json({ error: '이미지 파일을 업로드해주세요' });

    // 压缩图片
    await compressChatImage(file);

    const imageUrl = `/files/chat-images/${file.filename}`;
    return jsonResponse(res, { imageUrl });
  } catch (err) {
    console.error('채팅방 이미지 업로드 실패:', err);
    return res.status(500).json({ error: '이미지 업로드 실패' });
  }
});

// ===== 列表：GET /api/chat/rooms
router.get(Paths.Chat.Rooms, async (req, res) => {
  try {
    const { page = 1, limit = 20, search } = req.query as any;
    const p = Math.max(Number(page) || 1, 1);
    const l = Math.min(Math.max(Number(limit) || 20, 1), 100);

    const where: any = { status: 'active' };
    if (search) where.title = { contains: String(search), mode: 'insensitive' };

    const [rooms, total] = await Promise.all([
      prisma.chatRoom.findMany({
        where,
        skip: (p - 1) * l,
        take: l,
        orderBy: { createdAt: 'desc' },
        select: { id: true, title: true, displayName: true, coverUrl: true, description: true, createdAt: true },
      }),
      prisma.chatRoom.count({ where }),
    ]);

    return jsonResponse(res, { rooms, total, page: p, limit: l });
  } catch (err) {
    console.error('채팅방 목록 가져오기 실패:', err);
    return res.status(500).json({ error: '채팅방 목록 가져오기 실패' });
  }
});

// ===== 详情：GET /api/chat/rooms/:id
router.get(Paths.Chat.Rooms + '/:id', async (req, res) => {
  try {
    const { id } = req.params as any;

    const room = await prisma.chatRoom.findUnique({
      where: { id: BigInt(id) },
      include: {
        presets: {
          where: { isActive: true },
          orderBy: { sortOrder: 'asc' },
          select: { id: true, content: true, sortOrder: true },
        },
      },
    });

    if (!room) return res.status(404).json({ error: '채팅방이 존재하지 않습니다' });

    return jsonResponse(res, room);
  } catch (err) {
    console.error('채팅방 상세정보 조회 실패:', err);
    return res.status(500).json({ error: '채팅방 상세정보 조회 실패' });
  }
});

// ===== 检查是否需要密码：GET /api/chat/rooms/:id/check-password
router.get(Paths.Chat.Rooms + '/:id/check-password', async (req, res) => {
  try {
    const { id } = req.params as any;
    const user = await getCurrentUser(req);

    if (!user) return res.status(401).json({ error: '로그인이 필요합니다' });

    const room = await prisma.chatRoom.findUnique({
      where: { id: BigInt(id) },
      select: { id: true, password: true },
    });

    if (!room) return res.status(404).json({ error: '채팅방이 존재하지 않습니다' });

    // 管理员和合作伙伴可以直接进入
    if (user.role === 'admin' || user.role === 'partner') {
      return jsonResponse(res, { needPassword: false });
    }

    // 检查是否设置了密码
    const needPassword = !!room.password;
    return jsonResponse(res, { needPassword });
  } catch (err) {
    console.error('채팅방 비밀번호 확인 실패:', err);
    return res.status(500).json({ error: '비밀번호 확인에 실패했습니다' });
  }
});

// ===== 密码验证：POST /api/chat/rooms/:id/verify-password
router.post(Paths.Chat.Rooms + '/:id/verify-password', async (req, res) => {
  try {
    const { id } = req.params as any;
    const { password } = req.body ?? {};
    const user = await getCurrentUser(req);

    if (!user) return res.status(401).json({ error: '로그인이 필요합니다' });

    const room = await prisma.chatRoom.findUnique({
      where: { id: BigInt(id) },
      select: { id: true, password: true, creatorId: true },
    });

    if (!room) return res.status(404).json({ error: '채팅방이 존재하지 않습니다' });

    // 管理员和合作伙伴可以直接进入
    if (user.role === 'admin' || user.role === 'partner') {
      return jsonResponse(res, { success: true, needPassword: false });
    }

    // 如果聊天室没有设置密码，直接允许进入
    if (!room.password) {
      return jsonResponse(res, { success: true, needPassword: false });
    }

    // 验证密码
    if (String(password) !== room.password) {
      return res.status(400).json({ error: '비밀번호가 틀렸습니다' });
    }

    return jsonResponse(res, { success: true, needPassword: true });
  } catch (err) {
    console.error('채팅방 비밀번호 검증 실패:', err);
    return res.status(500).json({ error: '비밀번호 확인에 실패했습니다' });
  }
});

// ===== 历史：GET /api/chat/rooms/:id/history
router.get(Paths.Chat.Rooms + '/:id/history', async (req, res) => {
  try {
    const { id } = req.params as any;
    const limit = Math.min(Math.max(Number(req.query.limit) || 50, 1), 200);

    const history = await prisma.chatMessage.findMany({
      where: { roomId: BigInt(id), deletedAt: null },
      orderBy: { createdAt: 'desc' },
      take: limit,
      include: {
        user: { select: { id: true, nickname: true, name: true, avatarUrl: true } },
      },
    });

    // 升序返回
    history.reverse();

    const result = history.map((m) => ({
      id: String(m.id),
      content: m.content,
      messageType: m.messageType,
      imageUrl: m.imageUrl,
      username: m.user?.nickname || m.user?.name || '사용자',
      avatar: m.user?.avatarUrl || 'https://picsum.photos/32',
      timestamp: m.createdAt,
      isSystem: m.isSystem,
      senderUserId: m.userId ? String(m.userId) : undefined,
    }));

    return jsonResponse(res, { messages: result });
  } catch (err) {
    console.error('과거 메시지 조회 실패:', err);
    return res.status(500).json({ error: '과거 메시지 조회 실패' });
  }
});

// ===== SSE 实时：GET /api/chat/rooms/:id/stream

router.get(Paths.Chat.Rooms + '/:id/stream', async (req, res) => {
  const roomId = String((req.params as any).id);

  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
  res.flushHeaders?.();

  // 注册
  if (!chatSubscribers.has(roomId)) chatSubscribers.set(roomId, new Set());
  chatSubscribers.get(roomId)!.add(res);

  // 心跳
  const keepAlive = setInterval(() => res.write(': ping\n\n'), 30000);

  // 连接后推送系统欢迎词（包含预设）
  try {
    const room = await prisma.chatRoom.findUnique({
      where: { id: BigInt(roomId) },
      include: { presets: { where: { isActive: true }, orderBy: { sortOrder: 'asc' } } },
    });
    if (room?.presets?.length) {
      for (const p of room.presets) {
        res.write(`event: system\n` + `data: ${JSON.stringify({
          id: String(p.id),
          content: p.content,
          username: '시스템 메시지',
          avatar: 'https://picsum.photos/32',
          timestamp: new Date(),
          isSystem: true,
        })}\n\n`);
      }
    }
  } catch {}

  req.on('close', () => {
    clearInterval(keepAlive);
    chatSubscribers.get(roomId)?.delete(res);
  });
});

// ===== 发送消息：POST /api/chat/rooms/:id/messages
router.post(Paths.Chat.Rooms + '/:id/messages', async (req, res) => {
  try {
    const { id } = req.params as any;
    const user = await getCurrentUser(req);
    if (!user) return res.status(401).json({ error: '로그인되지 않음' });

    const { content, messageType = 'text', imageUrl } = req.body ?? {};

    // 验证消息内容
    if (messageType === 'text') {
      if (!content || String(content).trim() === '') {
        return res.status(400).json({ error: '메시지 내용이 비어있을 수 없습니다' });
      }
    } else if (messageType === 'image') {
      if (!imageUrl || String(imageUrl).trim() === '') {
        return res.status(400).json({ error: '이미지 URL이 비어있을 수 없습니다' });
      }
    } else {
      return res.status(400).json({ error: '지원하지 않는 메시지 유형입니다' });
    }

    const msg = await prisma.chatMessage.create({
      data: {
        roomId: BigInt(id),
        userId: user.id,
        content: messageType === 'text' ? String(content) : (imageUrl ? '이미지를 보냈습니다' : ''),
        messageType: String(messageType),
        imageUrl: messageType === 'image' ? String(imageUrl) : null,
      },
    });

    const payload = {
      id: String(msg.id),
      content: msg.content,
      messageType: msg.messageType,
      imageUrl: msg.imageUrl,
      username: user.nickname || user.name || '나',
      avatar: user.avatarUrl || 'https://picsum.photos/32',
      timestamp: msg.createdAt,
      senderUserId: String(user.id),
    };

    sendToChatRoom(String(id), 'message', payload);

    return jsonResponse(res, { ok: true, id: String(msg.id) });
  } catch (err) {
    console.error('메시지 전송 실패:', err);
    return res.status(500).json({ error: '메시지 전송 실패' });
  }
});

// ===== 获取礼物列表（普通用户可访问）：GET /api/chat/gifts
router.get('/gifts', async (req, res) => {
  try {
    const gifts = await prisma.gift.findMany({
      where: { isActive: true },
      orderBy: { createdAt: 'desc' },
      select: {
        id: true,
        name: true,
        iconUrl: true,
        pricePoints: true,
        isActive: true,
        effectPreset: true,
      },
    });
    return jsonResponse(res, gifts);
  } catch (err) {
    console.error('선물 목록 조회 실패:', err);
    return res.status(500).json({ error: '선물 목록 조회 실패' });
  }
});

// ===== 礼物广播（占位）：POST /api/chat/rooms/:id/gifts
router.post(Paths.Chat.Rooms + '/:id/gifts', async (req, res) => {
  try {
    const { id } = req.params as any;
    const user = await getCurrentUser(req);
    if (!user) return res.status(401).json({ error: '로그인되지 않음' });

    const { giftName } = req.body ?? {};
    const name = giftName ? String(giftName) : '선물';

    const payload = {
      id: String(Date.now()),
      content: `${name}을(를) 보냈습니다`,
      username: user.nickname || user.name || '나',
      avatar: user.avatarUrl || 'https://picsum.photos/32',
      timestamp: new Date(),
      isGift: true,
    };

    sendToChatRoom(String(id), 'gift', payload);

    return jsonResponse(res, { ok: true });
  } catch (err) {
    console.error('선물 방송 실패:', err);
    return res.status(500).json({ error: '선물 방송 실패' });
  }
});
// ===== 房间活跃用户搜索：GET /api/chat/rooms/:id/users
router.get(Paths.Chat.Rooms + '/:id/users', async (req, res) => {
  try {
    const { id } = req.params as any;
    const search = String((req.query.search ?? '') as any).trim();
    const limit = Math.min(Math.max(Number(req.query.limit) || 50, 1), 200);
    const windowSec = Math.min(Math.max(Number(req.query.windowSec) || 600, 60), 3600); // 1分钟~1小时，默认10分钟
    const threshold = new Date(Date.now() - windowSec * 1000);

    // 1) 取时间窗内的最近发言用户，按最后发言时间倒序
    const recentMsgs = await prisma.chatMessage.findMany({
      where: { roomId: BigInt(id), userId: { not: null }, createdAt: { gt: threshold }, deletedAt: null },
      orderBy: { createdAt: 'desc' },
      take: 2000,
      include: { user: { select: { id: true, nickname: true, name: true, avatarUrl: true, loginId: true } } },
    });

    // 去重并保留最后发言时间
    const map = new Map<string, { id: bigint; nickname?: string|null; name?: string|null; avatarUrl?: string|null; loginId: string; lastMessageAt: Date; lastMessagePreview: string }>();
    for (const m of recentMsgs) {
      if (!m.userId || !m.user) continue;
      const key = String(m.userId);
      if (!map.has(key)) {
        map.set(key, {
          id: m.user.id,
          nickname: m.user.nickname,
          name: m.user.name,
          avatarUrl: m.user.avatarUrl,
          loginId: m.user.loginId,
          lastMessageAt: m.createdAt,
          lastMessagePreview: m.content.slice(0, 30),
        });
      }
    }

    // 如时间窗为空，则降级为最近N条消息用户
    if (map.size === 0) {
      const fallback = await prisma.chatMessage.findMany({
        where: { roomId: BigInt(id), userId: { not: null }, deletedAt: null },
        orderBy: { createdAt: 'desc' },
        take: 1000,
        include: { user: { select: { id: true, nickname: true, name: true, avatarUrl: true, loginId: true } } },
      });
      for (const m of fallback) {
        if (!m.userId || !m.user) continue;
        const key = String(m.userId);
        if (!map.has(key)) {
          map.set(key, {
            id: m.user.id,
            nickname: m.user.nickname,
            name: m.user.name,
            avatarUrl: m.user.avatarUrl,
            loginId: m.user.loginId,
            lastMessageAt: m.createdAt,
            lastMessagePreview: m.content.slice(0, 30),
          });
        }
      }
    }

    // 转为数组并按 lastMessageAt 排序
    let users = Array.from(map.values()).sort((a, b) => b.lastMessageAt.getTime() - a.lastMessageAt.getTime());

    // 搜索过滤（loginId/nickname/name）
    if (search) {
      const key = search.toLowerCase();
      users = users.filter(u =>
        (u.loginId && u.loginId.toLowerCase().includes(key))
        || (u.nickname && u.nickname.toLowerCase().includes(key))
        || (u.name && u.name.toLowerCase().includes(key))
      );
    }

    users = users.slice(0, limit);

    return jsonResponse(res, { users: users.map(u => ({
      id: String(u.id),
      nickname: u.nickname,
      name: u.name,
      avatarUrl: u.avatarUrl,
      loginId: u.loginId,
      lastMessageAt: u.lastMessageAt,
      lastMessagePreview: u.lastMessagePreview,
    })) });
  } catch (err) {
    console.error('방 사용자 조회 실패:', err);
    return res.status(500).json({ error: '방 사용자 조회 실패' });
  }
});


// ===== 聊天室送礼（扣积分+记账+收礼入账）：POST /api/chat/rooms/:roomId/gifts/send
router.post(Paths.Chat.Rooms + '/:roomId/gifts/send', async (req, res) => {
  try {
    const user = await getCurrentUser(req);
    if (!user) return res.status(401).json({ error: '로그인되지 않음' });

    const { roomId } = req.params as any;
    const { giftId, quantity = 1, receiverUserId } = req.body ?? {};

    if (!giftId) return res.status(400).json({ error: 'giftId는 필수입니다' });
    if (!receiverUserId) return res.status(400).json({ error: 'receiverUserId는 필수입니다' });
    const qty = Math.max(1, Number(quantity || 1));

    const result = await prisma.$transaction(async (tx) => {
      const room = await tx.chatRoom.findUnique({ where: { id: BigInt(roomId) } });
      if (!room) throw new Error('채팅방이 존재하지 않습니다');

      const gift = await tx.gift.findUnique({ where: { id: BigInt(giftId) } });
      if (!gift || !gift.isActive) throw new Error('선물이 존재하지 않거나 판매 중단되었습니다');

      const receiver = await tx.user.findUnique({ where: { id: BigInt(receiverUserId) } });
      if (!receiver) throw new Error('선물 받을 사용자가 존재하지 않습니다');

      const total = BigInt(gift.pricePoints) * BigInt(qty);

      // 管理员发送礼物不扣积分，合作伙伴需要检查积分
      if (user.role !== 'admin') {
        const senderWallet = await tx.userWallet.findUnique({ where: { userId: user.id } });
        if (!senderWallet || senderWallet.pointsBalance < total) throw new Error('포인트가 부족합니다');

        // 扣发送者积分
        await tx.userWallet.update({ where: { userId: user.id }, data: { pointsBalance: senderWallet.pointsBalance - total } });
      }

      // 收礼人钱包（若不存在则创建）并加分
      let recvWallet = await tx.userWallet.findUnique({ where: { userId: receiver.id } });
      if (!recvWallet) {
        recvWallet = await tx.userWallet.create({ data: { userId: receiver.id, pointsBalance: BigInt(0) } });
      }
      await tx.userWallet.update({ where: { userId: receiver.id }, data: { pointsBalance: recvWallet.pointsBalance + total } });

      // 记录送礼
      const send = await tx.chatGiftSend.create({
        data: {
          chatRoomId: BigInt(roomId),
          giftId: gift.id,
          quantity: qty,
          unitPricePoints: gift.pricePoints,
          totalPoints: total,
          senderUserId: user.id,
          receiverUserId: receiver.id,
        },
      });

      // 账本：发送者支出（只有非管理员才记录）
      if (user.role !== 'admin') {
        await tx.pointLedger.create({
          data: {
            userId: user.id,
            deltaPoints: -total,
            reason: 'gift_send',
            relatedType: 'gift_send',
            relatedId: send.id,
          },
        });
      }

      // 账本：收礼者收入
      await tx.pointLedger.create({
        data: {
          userId: receiver.id,
          deltaPoints: total,
          reason: 'gift_income',
          relatedType: 'gift_send',
          relatedId: send.id,
        },
      });

      return { send, gift, receiver };
    });

    // SSE 广播礼物消息
    const sender = await getCurrentUser(req);
    const receiverName = (result.receiver.nickname || result.receiver.name || '사용자');
    const payload = {
      id: String(result.send.id),
      content: `${receiverName}에게 ${result.gift.name} x${result.send.quantity}을(를) 보냈습니다`,
      username: sender?.nickname || sender?.name || '나',
      avatar: sender?.avatarUrl || 'https://picsum.photos/32',
      timestamp: new Date(),
      isGift: true,
      giftId: String(result.gift.id),
      giftEffectPreset: result.gift.effectPreset || 'burst',
      quantity: Number(result.send.quantity || 1),
      senderUserId: sender ? String(sender.id) : undefined,
      receiverUserId: String(result.send.receiverUserId),
      receiverName,
      receiverAvatar: result.receiver.avatarUrl || 'https://picsum.photos/32',
    } as const;

    console.log('准备广播礼物消息到房间:', String((req.params as any).roomId));
    console.log('礼物消息payload:', JSON.stringify(payload, null, 2));
    console.log('当前聊天室订阅者数量:', chatSubscribers.get(String((req.params as any).roomId))?.size || 0);

    sendToChatRoom(String((req.params as any).roomId), 'gift', payload);

    return jsonResponse(res, result);
  } catch (err: any) {
    console.error('채팅방 선물 전송 실패:', err);
    return res.status(400).json({ error: err.message || '선물 전송 실패' });
  }
});



export default router;

